home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-09-11 | 4.2 KB | 144 lines | [TEXT/CWIE] |
- // PPAsyncHFSStoreStream.cp
- // Implements IAStoreStream for asynchronous access to an Macintosh HFS file.
- // Written by Blake Ward, User Experience Research, Apple Labs, Apple Computer, Inc.
-
-
- #include "PPAsyncHFSStoreStream.h"
- #include <string.h>
- #include <Errors.h>
- #include <Files.h>
-
- #include <LThread.h>
-
- #include "IAStorage.h"
-
-
- IAStorage* MakePPAsyncHFSStorage(short vRef, long dirId, const StringPtr name, OSType c, OSType t) {
- return IAMakeStorage(new PPAsyncHFSStoreStream(vRef, dirId, name, c, t));
- }
-
-
-
-
- PPAsyncHFSStoreStream::PPAsyncHFSStoreStream(short v, long d, const StringPtr n, OSType c, OSType t)
- : HFSStoreStream(v,d,n,c,t)
- {
- }
-
-
-
- PPAsyncHFSStoreStream::PPAsyncHFSStoreStream(short v, long d, const StringPtr n, OSType c, OSType t, bool o, bool w, short f)
- : HFSStoreStream(v,d,n,c,t,o,w,f) {
- }
-
-
-
-
- IAStoreStream* PPAsyncHFSStoreStream::Clone() {
- return new PPAsyncHFSStoreStream(vRefNum, dirID, fileName, creator, fileType, isOpen, isWritable, fRefNum);
- }
-
-
-
-
-
- void PPAsyncHFSStoreStream::Write(uint32 address, const byte* data, uint32 length) {
- OSErr err;
- SThreadParamBlk asyncPBlock;
- EventRecord theEvent;
- LThread *thrd;
-
- IAThrowIfNot(isOpen, StoreError);
-
- asyncPBlock.ioPB.F.ioParam.ioRefNum = fRefNum;
- asyncPBlock.ioPB.F.ioParam.ioBuffer = (Ptr)data;
- asyncPBlock.ioPB.F.ioParam.ioReqCount = length;
- asyncPBlock.ioPB.F.ioParam.ioPosMode = fsFromStart;
- asyncPBlock.ioPB.F.ioParam.ioPosOffset = address;
-
- // If we're currently inside a thread, then call async and suspend it
- if ((thrd = LThread::GetCurrentThread()) != nil && !LThread::InMainThread()) {
- // Only Yield if there are other threads ready to do something
- if (LThread::CountReadyThreads() > 1) {
- thrd->SetupAsynchronousResume(&asyncPBlock);
- err = ::PBWriteAsync(&asyncPBlock.ioPB.F);
- // Note that this call doesn't necessarily yield any time depending on
- // whether the write was immediately cached.
- err = thrd->SuspendUntilAsyncResume(&asyncPBlock);
- }
- else {
- asyncPBlock.ioPB.F.ioParam.ioCompletion = nil;
- err = ::PBWriteSync(&asyncPBlock.ioPB.F);
- }
- // In any case, if user events are pending, then give the main thread a chance
- // to process user I/O. For some reason, EventAvail doesn't detect mouseDown
- // events for us.
- if (::EventAvail(everyEvent, &theEvent) || ::Button())
- thrd->Yield();
- }
- else {
- asyncPBlock.ioPB.F.ioParam.ioCompletion = nil;
- err = ::PBWriteSync(&asyncPBlock.ioPB.F);
- }
-
- IAThrowIf(err, StoreError);
- IAAssert(asyncPBlock.ioPB.F.ioParam.ioActCount = length);
- }
-
-
-
-
- uint32
- PPAsyncHFSStoreStream::Read(uint32 address, byte* data, uint32 length) {
- OSErr err;
- SThreadParamBlk asyncPBlock;
- EventRecord theEvent;
- LThread *thrd;
-
- IAThrowIfNot(isOpen, StoreError);
-
- asyncPBlock.ioPB.F.ioParam.ioRefNum = fRefNum;
- asyncPBlock.ioPB.F.ioParam.ioBuffer = (Ptr)data;
- asyncPBlock.ioPB.F.ioParam.ioReqCount = length;
- asyncPBlock.ioPB.F.ioParam.ioPosMode = fsFromStart;
- asyncPBlock.ioPB.F.ioParam.ioPosOffset = address;
-
- // If we're currently inside a thread, then call async and suspend it
- if ((thrd = LThread::GetCurrentThread()) != nil && !LThread::InMainThread()) {
- // Only Yield if there are other threads ready to do something
- if (LThread::CountReadyThreads() > 1) {
- thrd->SetupAsynchronousResume(&asyncPBlock);
- err = ::PBReadAsync(&asyncPBlock.ioPB.F);
- // Note that this call doesn't necessarily yield any time depending on
- // whether the read was from the disk cache.
- err = thrd->SuspendUntilAsyncResume(&asyncPBlock);
- }
- else {
- asyncPBlock.ioPB.F.ioParam.ioCompletion = nil;
- err = ::PBReadSync(&asyncPBlock.ioPB.F);
- }
- // In any case, if user events are pending, then give the main thread a chance
- // to process user I/O. For some reason, EventAvail doesn't detect mouseDown
- // events for us.
- if (::EventAvail(everyEvent, &theEvent) || ::Button())
- thrd->Yield();
- }
- else {
- asyncPBlock.ioPB.F.ioParam.ioCompletion = nil;
- err = ::PBReadSync(&asyncPBlock.ioPB.F);
- }
-
- IAThrowIf(err && err != eofErr, StoreError);
- return asyncPBlock.ioPB.F.ioParam.ioActCount;
- }
-
-
- // This handy method is missing from HFSStoreStream
- void PPAsyncHFSStoreStream::GetFSSpec(FSSpec *fileSpec)
- {
- fileSpec->parID = dirID;
- fileSpec->vRefNum = vRefNum;
- BlockMoveData(fileName, fileSpec->name, fileName[0] + 1);
- }
-
-